//
//  KZMenuView.swift
//  KZSwiftMoudel
//
//  Created by 朱凯 on 2018/6/21.
//  Copyright © 2018年 JooKey. All rights reserved.
//

import UIKit

// MARK: ------ 菜单item结构体
struct KZMenuItem {
    
    let text: String
    let image: UIImage?
}
struct KZMenuConfig {
    
    var backgroundBlur: Bool = false
    var blurStyle: UIBlurEffectStyle = .dark
    var backgroundMask: Bool = false
    var menuBackgroundColor: UIColor = UIColor.white
    var menuSeparateColor: UIColor = UIColor.init(white: 0.9, alpha: 1)
    var menuTitleColor: UIColor = UIColor.black
    var menuTitleFont: UIFont = UIFont.systemFont(ofSize: 15)
}

// MARK: ------ 菜单位置option
struct KZMenuPosition: OptionSet {
    
    let rawValue: UInt
    
    static let left     = KZMenuPosition(rawValue: 1<<1)
    static let center   = KZMenuPosition(rawValue: 1<<2)
    static let right    = KZMenuPosition(rawValue: 1<<3)
    
    static let upward   = KZMenuPosition(rawValue: 1<<10)
    static let downward = KZMenuPosition(rawValue: 1<<11)
}

// MARK: ------ 菜单视图
class KZMenuView: UIControl {

    /// 选中回调
    var itemSelectClouse: (Int) -> Void = {_ in }
    
    /// 菜单列表
    let menuView = UITableView(frame: .zero, style: .plain)
    
    /// 配置
    var config = KZMenuConfig() {
        didSet {
            setNeedsLayout()
        }
    }
    
    /// 菜单内容数组
    var items: [KZMenuItem] = [KZMenuItem]() {
        didSet {
            setNeedsLayout()
        }
    }
    
    /// 菜单位置
    var position: KZMenuPosition = [.left, .downward] {
        didSet {
            setNeedsLayout()
        }
    }
    
    /// 菜单关联rect，如果要基于某一点则size=.zero即可，否则会根据6种位置自动计算
    var relatedRect: CGRect? {
        didSet {
            setNeedsLayout()
        }
    }
    
    /// 关联视图，计算该视图位于窗口的位置，然后设置关联rect
    var relatedView: UIView? {
        didSet {
            guard let view = relatedView else { return }
            guard let superview = view.superview else { return }
            
            let rect = superview.convert(view.frame, to: view.window!)
            relatedRect = rect
        }
    }
    
    /// 由于使用layoutsubviews方法，而我们在展示和隐藏的时候会用到view的tranform，为了避免不必要的麻烦，在隐藏时不调用layoutsubviews方法
    var isShow = false
    
    
    deinit {
        print("菜单销毁")
    }
    
    convenience init() {
        
        self.init(frame: .zero)
        
        setupUI()
    }
}


// MARK: ------ 视图绘制
extension KZMenuView {
    
    
    private func setupUI() {
        
        menuView.separatorStyle = .none
        menuView.bounces = false
        menuView.tableFooterView = UIView()
        menuView.delegate = self
        menuView.dataSource = self
        self.addSubview(menuView)
        
        menuView.register(KZMenuCell.self, forCellReuseIdentifier: "cell")
    }
    
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // 已经show了，就不用再布局了
        guard !isShow else { return }
        
        // 关联rect必须存在
        guard let rect = relatedRect else { return }
        
        // 配置
        menuView.backgroundColor = config.menuBackgroundColor
        
        // 设置菜单列表的frame
        menuView.frame = CGRect(origin: .zero, size: CGSize(width: 120, height: 40 * items.count + 10))
        
        // 设置图片绘制需要的属性
        var anchorX: CGFloat    = 0.5   // 锚点x
        var anchorY: CGFloat    = 0.5   // 锚点y
        var positionX: CGFloat  = 0.0   // 中心x(中心和锚点重合)
        var positionY: CGFloat  = 0.0   // 中心y
        var arrowX: CGFloat     = 0.0   // 箭头位置x
        var arrowY: CGFloat     = 0.0   // 箭头位置y
        var sym: CGFloat        = 1     // 符号位，由于绘制是从箭头开始绘制，如果菜单向上展开，则箭头向下，这时候符号位为-1
        if position.contains(.upward) {
            anchorY = 1
            positionY = rect.origin.y
            arrowY = menuView.height
            sym = -1
        }
        if position.contains(.downward) {
            anchorY = 0
            positionY = rect.origin.y + rect.size.height
            arrowY = 0
        }
        if position.contains(.left) {
            anchorX = 0
            positionX = rect.origin.x
            arrowX = 10 + 10
        }
        if position.contains(.center) {
            anchorX = 0.5
            positionX = rect.origin.x + rect.size.width / 2
            arrowX = menuView.width / 2
        }
        if position.contains(.right) {
            anchorX = 1
            positionX = rect.origin.x + rect.size.width
            arrowX = menuView.width - 10 - 10
        }
        
        menuView.layer.position = CGPoint(x: positionX, y: positionY)
        menuView.layer.anchorPoint = CGPoint(x: anchorX, y: anchorY)
        
        menuView.reloadData()
        
        // 遮罩图层，用于绘制出一个菜单的轮廓，并仅展示该轮廓内的内容
        let mask = CAShapeLayer()
        mask.backgroundColor = UIColor.white.cgColor
        let path = UIBezierPath()
        // 从箭头开始
        let points = [
            CGPoint(x: arrowX,
                    y: arrowY),
            CGPoint(x: arrowX - 10,
                    y: arrowY + 10 * sym),
            CGPoint(x: 0,
                    y: arrowY + 10 * sym),
            CGPoint(x: 0,
                    y: arrowY + menuView.height * sym),
            CGPoint(x: menuView.width,
                    y: arrowY + menuView.height * sym),
            CGPoint(x: menuView.width,
                    y: arrowY + 10 * sym),
            CGPoint(x: arrowX + 10,
                    y: arrowY + 10 * sym),
            ]
        
        
        for (i, point) in points.enumerated() {
            if i == 0 {
                path.move(to: point)
            } else {
                path.addLine(to: point)
            }
        }
        path.close()
        mask.path = path.cgPath
        
        menuView.layer.mask = mask
    }
}



// MARK: ------ TableView 代理
extension KZMenuView: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {

        return items.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell: KZMenuCell! = tableView.dequeueReusableCell(withIdentifier: "cell") as! KZMenuCell
        cell.cellConfig = config
        cell.item = items[indexPath.section]
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
       
        if position.contains(.upward) {
            if section == 0 { return 0 }
            else { return 1 }
        }
        if position.contains(.downward) {
            if section == 0 { return 10 }
        }

        return 0
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView()
        if self.tableView(tableView, heightForHeaderInSection: section) == 1 {
            view.backgroundColor = config.menuSeparateColor
        }
        return view
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {

        if position.contains(.upward) {
            if section == items.count - 1 { return 10 }
        }
        if position.contains(.downward) {
            if section == items.count - 1 { return 0 }
            else { return 1 }
        }

        return 0
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let view = UIView()
        if self.tableView(tableView, heightForFooterInSection: section) == 1 {
            view.backgroundColor = config.menuSeparateColor
        }
        return view
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        itemSelectClouse(indexPath.row)
    }
}


// MARK: ------ 事件
extension KZMenuView {
    
    func show() {
        
        // 已经准备好了
        self.isShow = false
        
        // 自身的点击dismiss事件
        self.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
        
        // 窗口
        let window = (UIApplication.shared.delegate as! AppDelegate).window!
        
        // 把自身添加到window上
        window.addSubview(self)

        self.snp.makeConstraints { (m) in
            m.edges.equalTo(window)
        }
        window.layoutIfNeeded()
        
        // 有模糊效果
        if config.backgroundBlur {
            let blurEffect = UIBlurEffect(style: config.blurStyle)
            let blurView = UIVisualEffectView(effect: blurEffect)
            blurView.tag = 111
            blurView.isUserInteractionEnabled = false
            blurView.frame = self.bounds
            blurView.alpha = 0.4
            self.insertSubview(blurView, at: 0)
        } else {
            if config.backgroundMask {
                self.backgroundColor = UIColor.black.withAlphaComponent(0)
            } else {
                self.backgroundColor = UIColor.clear
            }
        }
        
        
        
        menuView.transform = CGAffineTransform.init(scaleX: 0.01, y: 0.01)
        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: [], animations: {
            
            if self.config.backgroundBlur {
                self.viewWithTag(111)!.alpha = 1
            } else {
                if self.config.backgroundMask {
                    self.backgroundColor = UIColor.black.withAlphaComponent(0.4)
                } else {
                    //
                }
            }
            
            self.menuView.transform = CGAffineTransform.identity
            
        }) { (fin) in
            if fin {
                self.isShow = true
            }
        }
    }
    
    // 消失
    @objc func dismiss() {
        
        UIView.animate(withDuration: 0.25, animations: {
            
            if self.config.backgroundBlur {
                self.viewWithTag(111)!.alpha = 0
            } else {
                if self.config.backgroundMask {
                    self.backgroundColor = UIColor.black.withAlphaComponent(0)
                } else {
                    //
                }
            }
            
            self.menuView.transform = CGAffineTransform.init(scaleX: 0.01, y: 0.01)

        }) { (fin) in
            if fin {
                self.removeFromSuperview()
            }
        }
       
    }
}



// MARK: ------ cell
class KZMenuCell: UITableViewCell {
    
    private let line = UIView()
    private let iconView = UIImageView()
    private let titleLabel = UILabel()
    
    var cellConfig: KZMenuConfig? {
        didSet {
            guard let config = cellConfig else { return }
        
            titleLabel.font = config.menuTitleFont
            titleLabel.textColor = config.menuTitleColor
        }
    }
    
    var item: KZMenuItem? {
        didSet {
            guard let model = item else { return }
            
            titleLabel.text = model.text
            
            if let image = model.image {
                iconView.image = image
                iconView.snp.remakeConstraints { (m) in
                    m.left.equalTo(10)
                    m.centerY.equalTo(contentView)
                    m.width.height.equalTo(25)
                }
                titleLabel.snp.remakeConstraints { (m) in
                    m.left.equalTo(iconView.snp.right).offset(10)
                    m.right.equalTo(-10)
                    m.centerY.equalTo(iconView)
                }
            } else {
                iconView.snp.remakeConstraints { (m) in
                    m.left.equalTo(10)
                    m.width.height.equalTo(0)
                }
                titleLabel.snp.remakeConstraints { (m) in
                    m.left.equalTo(iconView.snp.right)
                    m.right.equalTo(-10)
                    m.centerY.equalTo(contentView)
                }
            }
            
        }
    }
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        self.selectionStyle = .none
        self.backgroundColor = UIColor.clear
        
        self.setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        
        // 图标
        contentView.addSubview(iconView)
        
        // 文字
        titleLabel.adjustsFontSizeToFitWidth = true
        titleLabel.textAlignment = .left
        contentView.addSubview(titleLabel)
    }
}
